﻿using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

public class ExcelTools : EditorWindow
{

	/// <summary>
	/// 当前编辑器窗口实例
	/// </summary>
	private static ExcelTools instance;

	/// <summary>
	/// Excel文件列表
	/// </summary>
	private static List<string> excelList;

	/// <summary>
	/// 项目根路径	
	/// </summary>
	private static string pathRoot;

	/// <summary>
	/// 滚动窗口初始位置
	/// </summary>
	private static Vector2 scrollPos;

	/// <summary>
	/// 输出格式索引
	/// </summary>
	private static int indexOfFormat=0;

	/// <summary>
	/// 输出格式
	/// </summary>
	private static string[] formatOption=new string[]{"JSON","CSV","XML"};

	/// <summary>
	/// 编码索引
	/// </summary>
	private static int indexOfEncoding=0;

	/// <summary>
	/// 编码选项
	/// </summary>
	private static string[] encodingOption=new string[]{"UTF-8","GB2312"};

	/// <summary>
	/// 特殊编码索引
	/// </summary>
	private static int indexOfStyle = 0;

	/// <summary>
	/// 特殊编码选项（可新增）
	/// </summary>
	private static string[] styleOption = new string[] { "普通", "age", "event" };

	/// <summary>
	/// 是否保留原始文件
	/// </summary>
	private static bool keepSource=true;

	/// <summary>
	/// 显示当前窗口	
	/// </summary>
	[MenuItem("Plugins/ExcelTools")]
	static void ShowExcelTools()
	{
		Init();
		//加载Excel文件
		LoadExcel();
		instance.Show();
	}

	void OnGUI()
	{
		DrawOptions();
		DrawExport();
	}

	/// <summary>
	/// 绘制插件界面配置项
	/// </summary>
	private void DrawOptions()
	{
		GUILayout.BeginHorizontal();
		EditorGUILayout.LabelField("请选择格式类型:",GUILayout.Width(85));
		indexOfFormat=EditorGUILayout.Popup(indexOfFormat,formatOption,GUILayout.Width(125));
		GUILayout.EndHorizontal();

		GUILayout.BeginHorizontal();
		EditorGUILayout.LabelField("请选择编码类型:",GUILayout.Width(85));
		indexOfEncoding=EditorGUILayout.Popup(indexOfEncoding,encodingOption,GUILayout.Width(125));
		GUILayout.EndHorizontal();
		//人生排位模拟器特需
		GUILayout.BeginHorizontal();
		EditorGUILayout.LabelField("请选择转换类型:", GUILayout.Width(85));
		indexOfStyle = EditorGUILayout.Popup(indexOfStyle, styleOption, GUILayout.Width(125));
		GUILayout.EndHorizontal();
		keepSource =GUILayout.Toggle(keepSource,"保留Excel源文件");
	}

	/// <summary>
	/// 绘制插件界面输出项
	/// </summary>
	private void DrawExport()
	{
		if(excelList==null) return;
		if(excelList.Count<1)
		{
			EditorGUILayout.LabelField("目前没有Excel文件被选中哦!");
		}
		else
		{
			EditorGUILayout.LabelField("下列项目将被转换为" + formatOption[indexOfFormat] + ":");



			GUILayout.BeginVertical();
			scrollPos=GUILayout.BeginScrollView(scrollPos,false,true,GUILayout.Height(150));
			foreach(string s in excelList)
			{
				GUILayout.BeginHorizontal();
				GUILayout.Toggle(true,s);

			

				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal();

				string excelPath = pathRoot+"/" + s;
				string output = "";
				string halfName = excelPath.Substring(excelPath.LastIndexOf("/") + 1);
				string SettingName= halfName.Insert(halfName.IndexOf(".") , "Setting");
				string fileName = SettingName.Replace(".xlsx", ".json");
				output = pathRoot + "/Assets/Resources/DataTable/" + fileName;

				//string output = excelPath.Replace(".xlsx", ".json");
				GUILayout.Toggle(true, output);
				GUILayout.EndHorizontal();

			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();

			//输出
			if(GUILayout.Button("转换"))
			{
				Convert();
			}
		}
	}

	/// <summary>
	/// 转换Excel文件
	/// </summary>
	private static void Convert()
	{
        string dataManagerPath = "Assets/Scripts/1.Manager/DataManager.cs"; // 更新为你的DataManager.cs路径
        // 读取DataManager.cs当前的内容
        string dataManagerContent = File.ReadAllText(dataManagerPath);
        StringBuilder listAndDictCode = new StringBuilder();
        StringBuilder loadExcelCode = new StringBuilder();
        StringBuilder caseCode = new StringBuilder();

        foreach (string assetsPath in excelList)
		{


			//获取Excel文件的绝对路径
			string excelPath=pathRoot + "/" + assetsPath;


			//构造Excel工具类
			ExcelUtility excel=new ExcelUtility(excelPath);

			//判断编码类型
			Encoding encoding=null;
			if(indexOfEncoding==0){
				encoding=Encoding.GetEncoding("utf-8");
			}else if(indexOfEncoding==1){
				encoding=Encoding.GetEncoding("gb2312");
			}

			////判断输出类型
			//string output="";
			//string halfName = excelPath.Substring(excelPath.LastIndexOf("/")+1);
			//Debug.Log(halfName);
		 //   string fileName ="Setting"+ halfName.Replace(".xlsx", ".json");

			//output = pathRoot + "/Resources/DataTable/" + fileName;


			//string excelPath = pathRoot + "/" + s;
			string output = "";
			string halfName = excelPath.Substring(excelPath.LastIndexOf("/") + 1);
			string SettingName = halfName.Insert(halfName.IndexOf("."), "Setting");
			string fileName = SettingName.Replace(".xlsx", ".json");
            string className = halfName.Split('.')[0]; // 假设命名约定
            //output = pathRoot + "/Assets/Resources/DataTable/" + fileName;




            output = Application.streamingAssetsPath + "/res/DataTable/" + fileName;

			if (indexOfFormat==0){
				switch (indexOfStyle)
				{
					case 0:
						excel.ConvertToJson(output, encoding);
						break;
                    case 1:
                        excel.RankStyleWithArrayToJson(output, encoding);
						break;
                    case 2:
                        excel.RankStyleToJson(output, encoding);
						break;
                    default:
						excel.ConvertToJson(output, encoding);
						break;
				}
			}
			else if(indexOfFormat==1){
				//output=excelPath.Replace(".xlsx",".csv");
				//excel.ConvertToCSV(output,encoding);
			}else if(indexOfFormat==2){
				//output=excelPath.Replace(".xlsx",".xml");
				//excel.ConvertToXml(output);
			}


			//判断是否保留源文件
			if (!keepSource)
			{
				FileUtil.DeleteFileOrDirectory(excelPath);
			}

			#region 自动生成代码

			//生成setting.cs文件
			string settingOuputPath = $"Assets/Scripts/4.Class/ChildClass/{className}Setting.cs";
            GenerateClassFromExcel(className, settingOuputPath, excel.ReturnExcelTitle());

            GenerateCodesForExcelFile(ref listAndDictCode, ref loadExcelCode, ref caseCode, dataManagerContent, className, SettingName.Split('.')[0]);
            // 更新DataManager.cs文件
            UpdateDataManagerCs(dataManagerContent, listAndDictCode, loadExcelCode, caseCode);

            #endregion
            //刷新本地资源
            AssetDatabase.Refresh();
		}

		//转换完后关闭插件
		//这样做是为了解决窗口
		//再次点击时路径错误的Bug
		if(instance!=null)
		instance.Close();

	}



    private static void GenerateClassFromExcel(string className,string output, List<string> fileInfoList)
    {
		if (fileInfoList.Count==0)
		{
			Debug.LogError("列表为空，无法创建Setting文件");
			return;
		}
        bool fileExists = File.Exists(output);


        List<string> existingLines = fileExists ? new List<string>(File.ReadAllLines(output)) : new List<string>();






        //StringBuilder existingContent = new StringBuilder();
        //existingContent.Append(File.ReadAllText(classFilePath));
        int insertIndex = 0; // 寻找类定义结束的位置
        StringBuilder newDefinitions = new StringBuilder();
        if (!fileExists)
        {
            // 假设已经填充了columnNames

            existingLines.Add($"public class {className}Setting : SettingBase");
            existingLines.Add("{");

            foreach (var columnName in fileInfoList)
            {
                // 将Excel列名转换为C#属性名，首字母大写
                string propertyName = columnName;
                existingLines.Add($"    public string {propertyName};");
            }
            existingLines.Add("}");
		}
		else
		{


            HashSet<string> existingProperties = new HashSet<string>();
            // 使用正则表达式匹配现有的属性定义
            string propertyPattern = @"public string (\w+);.*";
            foreach (var line in existingLines)
            {
                var match = Regex.Match(line.Trim(), propertyPattern);
                if (match.Success)
                {
                    existingProperties.Add(match.Groups[1].Value);
                }
            }

            //已存在setting.cs 文件
            foreach (var columnName in fileInfoList)
            {
                // 将Excel列名转换为C#属性名，首字母大写
				if (!existingProperties.Contains(columnName))
				{
                    newDefinitions.AppendLine($"    public string {columnName};");
                }
            }
			UpdateCsFileBasedOnExcel(fileInfoList, ref existingLines);
            insertIndex = existingLines.FindLastIndex(line => line.Contains("}")); // 寻找类定义结束的位置

        }
        //Debug.Log("当前插入位置" + insertIndex);
        // 将新的属性定义插入到类定义中
        existingLines.Insert(insertIndex, newDefinitions.ToString());
        File.WriteAllLines(output, existingLines);
		//Debug.Log("创建新的setting文件");
    }
	/// <summary>
	/// 更新setting文件
	/// </summary>
	/// <param name="columnNamesFromExcel"></param>
	/// <param name="lines"></param>
    static void UpdateCsFileBasedOnExcel(List<string> columnNamesFromExcel, ref List<string> lines)
    {

        List<string> updatedLines = new List<string>();

        // 解析出.cs文件中定义的所有属性
        List<string> propertyNamesInCsFile = lines
            .Where(line => line.Trim().StartsWith("public string"))
            .Select(line => line.Split(new[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries)[2].TrimEnd(';'))
            .ToList();

        // 找出已经不存在于Excel文件中的属性
        List<string> propertiesToRemove = propertyNamesInCsFile
            .Where(propertyName => !columnNamesFromExcel.Any(columnName => columnName.Equals(propertyName, System.StringComparison.OrdinalIgnoreCase)))
            .ToList();


        foreach (var line in lines)
        {
            bool removeLine = propertiesToRemove.Any(propToRemove => line.Contains($"public string {propToRemove};"));
            if (!removeLine)
            {
                updatedLines.Add(line);
            }
        }
        List<string> finalLines=RemoveExtraEmptyLines(updatedLines);
        lines = finalLines.ToList();
    }

    static List<string> RemoveExtraEmptyLines(List<string> lines)
    {
        List<string> result = new List<string>();
       // bool previousLineWasEmpty = false;

        foreach (var line in lines)
        {
            if (string.IsNullOrWhiteSpace(line))
            {
				Debug.Log("空白");
				/* if (!previousLineWasEmpty)
				 {
					 result.Add(line);
					 previousLineWasEmpty = true;
				 }*/
				continue;
            }
            else
            {
                result.Add(line);
                //previousLineWasEmpty = false;
            }
        }
		Debug.Log(result.Count);
        return result;
    }
    private static void GenerateCodesForExcelFile(ref StringBuilder listAndDictCode, ref StringBuilder loadExcelCode, ref StringBuilder caseCode, string dataManagerContent, string nameWithoutExtension, string className)
    {
        // 检查是否已经存在相关的代码
        string variableName = System.Char.ToLowerInvariant(nameWithoutExtension[0]) + nameWithoutExtension.Substring(1); // 只有首字母缩写，后面的大写保留
        string listPattern = $"List<{className}> {variableName}List";
        string dictPattern = $"Dictionary<int, {className}> {variableName}Dic";
        string casePattern = $"case \"{className}\":";

        if (!dataManagerContent.Contains(listPattern) && !dataManagerContent.Contains(dictPattern))
        {
            // 生成新的列表和字典定义
            listAndDictCode.AppendLine($"	public List<{className}> {variableName}List = new List<{className}>();");
            listAndDictCode.AppendLine($"	public Dictionary<int, {className}> {variableName}Dic = new Dictionary<int, {className}>();");
            listAndDictCode.AppendLine();
            // 生成加载代码
            loadExcelCode.AppendLine($"            LoadExcelForJson(out {variableName}List, {variableName}Dic);");
        }

        if (!dataManagerContent.Contains(casePattern))
        {
            // 生成新的case语句
            caseCode.AppendLine($"            case \"{className}\":");
            caseCode.AppendLine($"                if (Instance.{variableName}Dic.ContainsKey(settingid))");
            caseCode.AppendLine($"                    t = Instance.{variableName}Dic[settingid] as T;");
            caseCode.AppendLine($"                break;");
        }
    }

    private static void UpdateDataManagerCs(string dataManagerContent, StringBuilder listAndDictCode, StringBuilder loadExcelCode, StringBuilder caseCode)
    {
        // 插入生成的代码
        string updatedContent = InsertGeneratedCodeIntoDataManager(dataManagerContent, listAndDictCode.ToString(), "// AUTO-GENERATED LISTS AND DICTIONARIES START", "// AUTO-GENERATED LISTS AND DICTIONARIES END");
        updatedContent = InsertGeneratedCodeIntoDataManager(updatedContent, loadExcelCode.ToString(), "// AUTO-GENERATED LOADING CODE START", "// AUTO-GENERATED LOADING CODE END");
        updatedContent = InsertGeneratedCodeIntoDataManager(updatedContent, caseCode.ToString(), "// AUTO-GENERATED CASES START", "// AUTO-GENERATED CASES END");

        File.WriteAllText("Assets/Scripts/1.Manager/DataManager.cs", updatedContent);
        AssetDatabase.Refresh();
        Debug.Log("Excel code generation completed.");
    }

    private static string InsertGeneratedCodeIntoDataManager(string content, string newCode, string startMarker, string endMarker)
    {
        int startMarkerIndex = content.IndexOf(startMarker) + startMarker.Length;
        int endMarkerIndex = content.IndexOf(endMarker);

        // 如果找不到标记，则直接返回原始内容
        if (startMarkerIndex < 0 || endMarkerIndex < 0 || startMarkerIndex >= endMarkerIndex)
        {
            Debug.LogError($"Markers not found in DataManager.cs. Please ensure both {startMarker} and {endMarker} exist.");
            return content;
        }

        // 分割原始内容为三部分：标记之前、标记区间、标记之后
        string beforeMarker = content.Substring(0, startMarkerIndex);
        string afterMarker = content.Substring(endMarkerIndex);
        string markedSection = content.Substring(startMarkerIndex, endMarkerIndex - startMarkerIndex);

        // 检查新代码是否已存在于标记区间内
        if (!markedSection.Contains(newCode))
        {
            // 如果不存在，将新代码追加到标记区间的开始处
            markedSection = "\n" + newCode + markedSection;
        }

        // 重建并返回更新后的内容
        return beforeMarker + markedSection + afterMarker;
    }

    /// <summary>
    /// 加载Excel
    /// </summary>
    private static void LoadExcel()
	{
		if(excelList==null) excelList=new List<string>();
		excelList.Clear();
		//获取选中的对象
		object[] selection=(object[])Selection.objects;
		//判断是否有对象被选中
		if(selection.Length==0)
			return;
		//遍历每一个对象判断不是Excel文件
		foreach(Object obj in selection)
		{
			string objPath=AssetDatabase.GetAssetPath(obj);
			if(objPath.EndsWith(".xlsx"))
			{
				excelList.Add(objPath);
			}
		}
	}

	private static void Init()
	{
		//获取当前实例
		instance=EditorWindow.GetWindow<ExcelTools>();
		//初始化
		pathRoot=Application.dataPath;
		//注意这里需要对路径进行处理
		//目的是去除Assets这部分字符以获取项目目录
		//我表示Windows的/符号一直没有搞懂
		pathRoot=pathRoot.Substring(0,pathRoot.LastIndexOf("/"));
		excelList=new List<string>();
		scrollPos=new Vector2(instance.position.x,instance.position.y+75);
	}

	void OnSelectionChange() 
	{
		//当选择发生变化时重绘窗体
		pathRoot = Application.dataPath;
		pathRoot = pathRoot.Substring(0, pathRoot.LastIndexOf("/"));
		Show();
		LoadExcel();
		Repaint();
	}
}
